package com.dji.sample.common.util;

import com.dji.sample.common.util.kmlModel.TravelRecordRequest;

import io.minio.ObjectWriteResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;


import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author yjt
 * @date 2022-09-27
 * @description:
 */
@Component
@Slf4j
public class KmlUtil {
    @Value("${tmp.file.logo}")
    public String LOGO;

    @Value("${tmp.file.path}")
    public String TMP_PATH;

    @Autowired
    MinioUtil minioUtil;

    public static final String NORMAL_KML="kml/";


    public  ObjectWriteResponse setTravelsKml(List<TravelRecordRequest> travelRecords, String fileName) throws Exception {
        Element root = DocumentHelper.createElement("kml");
        Document document = DocumentHelper.createDocument(root);
        //根节点添加属性
        root.addAttribute("xmlns", "http://www.opengis.net/kml/2.2")
                .addAttribute("xmlns:gx", "http://www.google.com/kml/ext/2.2")
                .addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
                .addAttribute("xsi:schemaLocation",
                        "http://www.opengis.net/kml/2.2 http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd http://www.google.com/kml/ext/2.2 http://code.google.com/apis/kml/schema/kml22gx.xsd");
        Element documentElement = root.addElement("Document");
        documentElement.addElement("name").addText(fileName);
        documentElement.addElement("Snippet").addText("");
        Element folderElement = documentElement.addElement("Folder");//添加一个目录
        folderElement.addAttribute("id", "FeatureLayer0");
        folderElement.addElement("name").addText("轨迹点位"); //名称
        folderElement.addElement("Snippet").addText(""); //显示在Google Earth之中的对description的简短概要.
        //生成点位图标数据
        int i = 0;
        for (TravelRecordRequest travelRecord : travelRecords) {
            i++;
            Element placeMarkElement = folderElement.addElement("Placemark");//在文件夹中添加一个地标
            placeMarkElement.addAttribute("id", String.valueOf(i));
            placeMarkElement.addElement("name").addText("点位" + i);
            placeMarkElement.addElement("Snippet").addText("");
            placeMarkElement.addElement("description").addText("");//简介
            placeMarkElement.addElement("styleUrl").addText("#MyStyle");//风格
            Element pointElement = placeMarkElement.addElement("Point");
            pointElement.addElement("altitudeMode").addText("clampToGround");
            //添加点位的经纬度坐标以及高度(显示时绘制高度m)
            pointElement.addElement("coordinates").addText(travelRecord.lng + "," + travelRecord.lat + "," + travelRecord.height);//可以是是任何几何形状的子元素，定义每一个点的经度、纬度和高度(按照严格的顺序). 多个点使用空格隔开，经纬度按照WGS84标准.
        }
        //生成轨迹线路径数据
        Element lineElement = documentElement.addElement("Placemark");//在文件夹外添加一个地标
        lineElement.addElement("name").addText("轨迹线");
        lineElement.addElement("description").addText("");
        lineElement.addElement("styleUrl").addText("#MyStyle");
        Element pointElement = lineElement.addElement("LineString");
        pointElement.addElement("altitudeMode").addText("absolute");
        pointElement.addElement("extrude").addText("1");
        pointElement.addElement("tessellate").addText("1");
        String linedata = "";
        //每个坐标以及高度用换行符或空格分开
        for (TravelRecordRequest travelRecord : travelRecords) {
            linedata = linedata + "\n" + travelRecord.lng + "," + travelRecord.lat + "," + travelRecord.height;
        }
        pointElement.addElement("coordinates").addText(linedata);
        //生成显示风格
        Element styleElement = documentElement.addElement("Style");//Style节点
        styleElement.addAttribute("id", "MyStyle");
        // IconStyle 图标风格
        Element iconStyleElement = styleElement.addElement("IconStyle");
        Element iconElement = iconStyleElement.addElement("Icon");
        if (LOGO != null && !"".equals(LOGO)) {
            iconElement.addElement("href").addText(LOGO);//在线图标
        }
        iconStyleElement.addElement("scale").addText("0.250000");
        // LabelStyle  标签风格
        Element labelStyleElement = styleElement.addElement("LabelStyle");
        labelStyleElement.addElement("color").addText("ff00ffff");
        labelStyleElement.addElement("scale").addText("0.000000");
        // PolyStyle 图形风格
        Element polyStyleElement = styleElement.addElement("PolyStyle");
        polyStyleElement.addElement("color").addText("ffff0055");
        polyStyleElement.addElement("outline").addText("0");

        // LineStyle  路径线风格
        Element lineStyleElement = styleElement.addElement("LineStyle");
        lineStyleElement.addElement("color").addText("ffff0055");
        lineStyleElement.addElement("width").addText("4");

        //创建kml到本地
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");
        XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(TMP_PATH + fileName + "_.kml"), format);

        xmlWriter.write(document);

        xmlWriter.close();
        //开始对文件进行压缩，一个kml文件其实是一个压缩文件，里面包含一个kml文件和一个png图标
//        String[] strs = new String[1];
//        strs[0] = path + fileName + "_.kml";
//    //    strs[1] = "D:/web/Travels/images/img_mark.png";//这里写图片的路径  如果使用在线图标这段代码屏蔽
//        writeKml(strs, path + fileName);//压缩
//        System.out.println("kml生成成功");
        //上传OSS
        String path = TMP_PATH + fileName + "_.kml";
        File file = new File(path);
        InputStream inputStream = new FileInputStream(file);
        try {
            MultipartFile multipartFile = new MockMultipartFile(file.getName(),file.getName(),ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
            return minioUtil.upload(NORMAL_KML+fileName + "_.kml", multipartFile);
        }catch (Exception e){
            log.error("oss上传异常",e);
        }finally {
            inputStream.close();
            file.deleteOnExit();
        }
        return null;
    }


    public static void writeKml(String[] strs, String kmlName) throws IOException {
        OutputStream os = new BufferedOutputStream(new FileOutputStream(kmlName + ".zip"));
        ZipOutputStream zos = new ZipOutputStream(os);
        byte[] buf = new byte[8192];
        int len;
        for (int i = 0; i < strs.length; i++) {
            File file = new File(strs[i]);
            if (!file.isFile()) {
                continue;
            }
            ZipEntry ze = new ZipEntry(file.getName());
            zos.putNextEntry(ze);
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            while ((len = bis.read(buf)) > 0) {
                zos.write(buf, 0, len);
            }
            zos.closeEntry();
            bis.close();
        }
        zos.closeEntry();
        zos.close();
        os.close();
    }

}
